import DetailWrap from "@/components/DetailWrap";
import FormByData, { FormByDataRef, FormItemType } from "@/components/FormByData/FormByData";
import { CodeGenerate, CreateCodeGenerateFieldType, CreateCodeGenerateReq, LookupListItem, ParentFind } from "@/typings/api";
import { TabsProps, Tabs, Button, message, Spin } from "antd";
import { createContext, Dispatch, SetStateAction, useEffect, useRef, useState } from "react";
import FieldsConfig, { FieldConfigRef } from "./components/FieldsConfig";
import LookupList, { LookupListRef } from "./components/LookupList";
import { SaveOutlined } from "@ant-design/icons";
import { useNavigate, useSearchParams } from "react-router-dom";
import { createCodeGenerate, getCodeGenerateRecord, updateCodeGenerate } from "@/api/codeGenerate";
import { Operations, ResultTypes } from "@/constant/codeGenerate";
import PermissionSelect from "@/components/PermissionSelect";

type BasicInfoFormField = Pick<CodeGenerate, "modelName" | "collectionName" | "desc" | "operations" | "resultTypes" | "pageName" | "permissionKey">;
export const CodeGenerateConfigContext = createContext<{
    fields: readonly CreateCodeGenerateFieldType[];
    setFields: Dispatch<SetStateAction<readonly CreateCodeGenerateFieldType[]>>;
    lookupList: readonly LookupListItem[];
    setLookupList: Dispatch<SetStateAction<readonly LookupListItem[]>>;
}>({ fields: [], setFields: () => null, lookupList: [], setLookupList: () => null });

const CodeGenerateConfig = () => {
    const basicInfoFormItems: FormItemType<BasicInfoFormField>[] = [
        { name: "modelName", label: "模型名", required: true },
        { name: "pageName", label: "页面名" },
        { name: "collectionName", label: "集合名" },
        { name: "permissionKey", label: "权限标识", component: PermissionSelect },
        {
            name: "operations",
            label: "生成接口类型",
            options: Object.entries(Operations).map(([value, label]) => ({ value, label })),
            componentProps: { mode: "multiple" },
        },
        {
            name: "resultTypes",
            label: "代码类型",
            options: Object.entries(ResultTypes).map(([value, label]) => ({ value, label })),
            componentProps: { mode: "multiple" },
        },
        { name: "desc", label: "描述", type: "textarea" },
    ];
    const parentFindFormItems: FormItemType<ParentFind>[] = [
        { name: "localField", label: "关联字段" },
        { name: "parentModelName", label: "父模型" },
    ];
    const basicInfoFormRef = useRef<FormByDataRef<BasicInfoFormField> | null>(null);
    const parentFindFormRef = useRef<FormByDataRef<ParentFind> | null>(null);
    const fieldsConfigFormRef = useRef<FieldConfigRef | null>(null);
    const lookupListFormRef = useRef<LookupListRef | null>(null);
    const items: TabsProps["items"] = [
        {
            key: "basicInfo",
            label: (
                <span>
                    <span className="text-red-500 mr-1">*</span>基础信息
                </span>
            ),
            children: (
                <FormByData
                    ref={basicInfoFormRef}
                    formItems={basicInfoFormItems}
                    formProps={{ style: { width: "400px" }, layout: "horizontal", initialValues: { operations: [] } }}
                    cols={1}
                />
            ),
        },
        {
            key: "fieldsConfig",
            label: "字段配置",
            children: <FieldsConfig ref={fieldsConfigFormRef} />,
        },
        {
            key: "parentFind",
            label: "父查子分页",
            children: (
                <FormByData
                    formItems={parentFindFormItems}
                    formProps={{ style: { width: "400px" }, layout: "horizontal" }}
                    cols={1}
                    required
                    ref={parentFindFormRef}
                />
            ),
        },
        {
            key: "lookupList",
            label: "关联查询",
            children: <LookupList ref={lookupListFormRef} />,
        },
    ];
    const [fields, setFields] = useState<readonly CreateCodeGenerateFieldType[]>([]);
    const [lookupList, setLookupList] = useState<readonly LookupListItem[]>([]);
    const [params] = useSearchParams();
    const _id = params.get("_id");
    const navigate = useNavigate();
    const submit = async () => {
        let fieldsData, parentFindData, basicInfoData, lookupListData;
        try {
            basicInfoData = await basicInfoFormRef.current?.validate();
        } catch {
            return message.warning("请检查基础信息表单");
        }

        try {
            fieldsData = await fieldsConfigFormRef.current?.validate();
        } catch {
            return message.warning("请检查字段配置表单");
        }

        try {
            const data = await parentFindFormRef.current!.getFieldsValue();
            if (Object.values(data).some(item => item !== undefined)) parentFindData = await parentFindFormRef.current?.validate();
        } catch {
            return message.warning("请检父查子分页表单");
        }

        try {
            lookupListData = await lookupListFormRef.current?.validate();
        } catch {
            return message.warning("请检查字段配置表单");
        }
        const fields = Object.values(fieldsData!).map(item => ({
            ...item,
            isTable: item.isTable === "true",
            isForm: item.isForm === "true",
            required: item.required === "true",
            unique: item.unique === "true",
        }));
        const data: CreateCodeGenerateReq = { ...basicInfoData!, fields };
        if (lookupListData) data.lookupList = Object.values(lookupListData);
        if (parentFindData) data.parentFind = parentFindData;
        if (!_id) {
            await createCodeGenerate(data);
            message.success("创建成功");
        } else {
            await updateCodeGenerate({ ...data, _id: _id as string });
            message.success("更新成功");
        }
        navigate("/system/codeGenerate", { replace: true });
    };

    const [loading, setLoading] = useState(false);
    const initData = async () => {
        if (!_id) return;
        setLoading(true);
        try {
            const { data = {} } = await getCodeGenerateRecord(_id);
            const { fields = [], parentFind = {}, lookupList = [], ...basicInfo } = data;
            const { localField, parentModelName } = parentFind;
            basicInfoFormRef.current?.setFieldsValue(basicInfo);
            parentFindFormRef.current?.setFieldsValue({ localField, parentModelName });
            setFields(
                fields.map((item: CreateCodeGenerateFieldType) => ({
                    ...item,
                    isTable: item.isTable ? "true" : "false",
                    isForm: item.isForm ? "true" : "false",
                    required: item.required ? "true" : "false",
                    unique: item.unique ? "true" : "false",
                }))
            );
            setLookupList(lookupList);
        } finally {
            setLoading(false);
        }
    };
    useEffect(() => {
        initData();
    }, []);
    return (
        <Spin spinning={loading}>
            <CodeGenerateConfigContext.Provider value={{ fields, setFields, lookupList, setLookupList }}>
                <DetailWrap
                    title="代码生成配置"
                    backUrl="/system/codeGenerate"
                    actionMore={
                        <Button type="primary" icon={<SaveOutlined />} onClick={submit}>
                            保存
                        </Button>
                    }
                >
                    <Tabs defaultActiveKey="1" items={items.map(item => ({ ...item, forceRender: true }))} />
                </DetailWrap>
            </CodeGenerateConfigContext.Provider>
        </Spin>
    );
};

export default CodeGenerateConfig;
